home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
loading
/
IncrementalLoad.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-18
|
54KB
|
1,931 lines
/* begincopyright
Copyright (c) 1988 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA 94304
endcopyright */
/*
* IncrementalLoad.c
*
* Demers, January 18, 1991 8:20:01 am PST
* Aizawa, April 6, 1990 3:13:12 pm PDT
*/
#include "xr/BasicTypes.h"
#include "xr/Errno.h"
#include "xr/Threads.h"
#include "xr/ThreadsBackdoor.h"
#include "xr/ThreadsTermination.h"
#include "xr/ThreadsMsg.h"
#include "xr/IncrementalLoad.h"
#include "xr/IncrementalLoadPrivate.h"
#include <ctype.h>
#include <fcntl.h>
#if defined(UNIX) || defined(UNIXDEBUG)
#include <stdio.h>
#endif
#define PREEMPTABLE_READ 1
#define DEFAULT_PBYTES_FROM_TBYTES(b) (((unsigned)(b)) >> 6)
/*
* Lock
*/
XR_ILError
XR_LockIncrementalLoadState(wait)
bool wait;
{
XR_ILSymTab ilst = XR_ilSymTab;
XR_ILError result = NIL;
XR_MonitorEntry(&(ilst->ilst_ml));
if( ilst->ilst_locked && (!wait) ) {
result = XR_ILMakeError(FALSE, ETIMEDOUT, "locked");
goto Out;
}
/* assert: (not locked) || wait */
while( ilst->ilst_locked ) {
int waitResult = XR_WaitCV( &(ilst->ilst_avail), &(ilst->ilst_ml) );
if( waitResult != 0 ) {
result = XR_ILMakeError( FALSE, XR_EABORTED,
"LockIncrementalLoadState: aborted");
goto Out;
}
}
ilst->ilst_locked = TRUE;
Out:
XR_MonitorExit(&(ilst->ilst_ml));
return result;
}
XR_ILError
XR_UnlockIncrementalLoadState()
{
XR_ILSymTab ilst = XR_ilSymTab;
XR_ILError result = NIL;
XR_MonitorEntry(&(ilst->ilst_ml));
if( ilst->ilst_locked ) {
ilst->ilst_locked = FALSE;
XR_Notify(&(ilst->ilst_avail));
} else {
result = XR_ILMakeError( FALSE, EINVAL,
"UnlockIncrementalLoadState: not locked");
}
XR_MonitorExit(&(ilst->ilst_ml));
return result;
}
/*
*
* ILFile table stuff
*
*/
static char *
XR_CompressSlashesInPlace(path)
char *path;
{
char *from;
char *to;
char c;
from = to = path;
for(;;) {
c = (*to++ = *from++);
if( c == 0 ) break;
if( c == '/' ) {
while( *from == '/' ) from++;
}
}
to -= 2;
if( (to > path) && (*to == '/') ) *to = 0;
return path;
}
static XR_ILFileTabEntry
XR_ILCreateILFTE(ilst, fName, fOffset)
XR_ILSymTab ilst;
char *fName;
unsigned fOffset;
{
XR_ILFileTabEntry ilfte;
ilfte = (XR_ILFileTabEntry) XR_PZcalloc(
ilst->ilst_zone, sizeof(struct XR_ILFileTabEntryRep), 1);
if( ilfte == NIL ) return NIL;
if( fName != NIL ) {
extern char *(XR_ExpandPath());
char *nameCopy = XR_ExpandPath(fName);
if( nameCopy == NIL ) return NIL;
if( nameCopy == fName ) {
nameCopy = (char *)
XR_PZmalloc( ilst->ilst_zonePtrFree, strlen(fName)+1 );
if( nameCopy == NIL ) return NIL;
strcpy(nameCopy, fName);
}
ilfte->ilfte_ilfe.ilfe_fName = XR_CompressSlashesInPlace(nameCopy);
} else {
ilfte->ilfte_ilfe.ilfe_fName = "";
}
ilfte->ilfte_ilfe.ilfe_fOffset = fOffset;
ilfte->ilfte_ilfe.ilfe_seqNum = ilst->ilst_seqNum;
ilst->ilst_seqNum += 1;
return ilfte;
}
XR_ILFileEntry
XR_ILGetPrevFileEntry(ilfe)
XR_ILFileEntry ilfe;
{
if( ilfe == NIL ) {
return ((XR_ILFileEntry)(XR_ilSymTab->ilst_ilfte));
} else {
return ( (XR_ILFileEntry) (((XR_ILFileTabEntry)(ilfe))->ilfte_prev) );
}
}
/* static */ void
XR_ILAddVersionStamp(ilfe, vMagic, vLen, vStamp)
XR_ILFileEntry ilfe;
unsigned vMagic;
unsigned vLen;
char * vStamp;
{
ilfe->ilfe_vMagic = vMagic;
ilfe->ilfe_vLen = vLen;
ilfe->ilfe_vStamp = vStamp;
ilfe->ilfe_vMagic = vMagic;
}
XR_ILFileEntry
XR_ILAddVersionStampUsingPC(pc, vMagic, vLen, vStamp)
caddr_t pc;
unsigned vMagic;
unsigned vLen;
char * vStamp;
{
XR_ILSymTabEntry ilste;
XR_ILFileEntry ilfe;
ilste = (XR_ILSymTabEntry) XR_ILLookupSymEntryByValue(pc);
if( ilste == NIL ) return NIL;
ilfe = ilste->ilste_ilse.ilse_ilfe;
XR_ILAddVersionStamp(ilfe, vMagic, vLen, vStamp);
return ilfe;
}
/*
* Default GC root stuff
*/
/*
??? INTERIM ???
When we commit, we tell the GC (once) about all the
committed roots. This won't allow us to unload, but currently we
can't do that anyway ...
*/
static void
XR_ILGCCallback(seg, data)
XR_Seg seg;
XR_Pointer data;
{
extern void XR_add_data_list(/* XR_Pointer low, hi */); /* from GC.h */
if( seg->seg_addr == NIL ) XR_Panic("ILGCCallBack 0");
if( data != NIL ) XR_Panic("ILGCCallBack 1");
XR_add_data_list( seg->seg_addr, seg->seg_addr + seg->seg_bytes );
}
static void
XR_ILTellCollectorAboutRoots(ilst, ilfte)
XR_ILSymTab ilst;
XR_ILFileTabEntry ilfte;
{
if( ilfte->ilfte_gcRootEnumerator != NIL ) {
(*(ilfte->ilfte_gcRootEnumerator))(
XR_ILGCCallback,
NIL,
ilfte->ilfte_gcRootEnumeratorData
);
} else {
XR_ConsoleMsg( "ILTellCollectorAboutRoots botch, file %s\n",
ilfte->ilfte_ilfe.ilfe_fName );
}
}
/*
??? END of INTERIM stuff
*/
static void
XR_ILDefaultBootFileGCRootEnumerator(gcCallback, gcCallbackData, data)
XR_GCRootCallback gcCallback /*(XR_Seg seg, XR_Pointer data)*/ ;
XR_Pointer gcCallbackData;
XR_Pointer data;
{
if( XR_sysArea->sa_sharedDataSeg.seg_bytes > 0 )
(*gcCallback)( &(XR_sysArea->sa_sharedDataSeg), gcCallbackData );
#ifdef XXXX
if( XR_sysArea->sa_sharedBSSSeg.seg_bytes > 0 )
(*gcCallback)( &(XR_sysArea->sa_sharedBSSSeg), gcCallbackData );
if( XR_sysArea->sa_sharedCommonSeg.seg_bytes > 0 )
(*gcCallback)( &(XR_sysArea->sa_sharedCommonSeg), gcCallbackData );
#endif
}
static void
XR_ILDefaultGCRootEnumerator(gcCallback, gcCallbackData, data)
XR_GCRootCallback gcCallback /*(XR_Seg seg, XR_Pointer data)*/ ;
XR_Pointer gcCallbackData;
XR_Pointer data;
{
struct XR_SegRep seg;
XR_ILFileTabEntry ilfte = ((XR_ILFileTabEntry)(data));
# define CondCallback(addr,bytes) if( (bytes) > 0 ) { \
seg.seg_addr = ((XR_Pointer)(addr)); seg.seg_bytes = (bytes); \
(*gcCallback)( &seg, gcCallbackData ); }
CondCallback(ilfte->ilfte_ilfe.ilfe_dAddr, ilfte->ilfte_ilfe.ilfe_dBytes);
CondCallback(ilfte->ilfte_ilfe.ilfe_bAddr, ilfte->ilfte_ilfe.ilfe_bBytes);
CondCallback(ilfte->ilfte_ilfe.ilfe_cAddr, ilfte->ilfte_ilfe.ilfe_cBytes);
# undef CondCallback
}
void
XR_ILSetGCRootEnumerator(ilst, ilfte, gcRootEnumerator, gcRootEnumeratorData)
XR_ILSymTab ilst;
XR_ILFileTabEntry ilfte;
XR_GCRootEnumerator gcRootEnumerator;
XR_Pointer gcRootEnumeratorData;
{
ilfte->ilfte_gcRootEnumerator = NIL;
ilfte->ilfte_gcRootEnumeratorData = gcRootEnumeratorData;
ilfte->ilfte_gcRootEnumerator = gcRootEnumerator;
}
/*
*
* Symbol Table
*
* Hash table by name of text or external symbols.
* Skiplist by value of (text, external data, external bss) symbols.
*
*/
#define XR_ILST_INIT_NUM_HDRS (8*1024) /* must be power of 2 */
#define XR_ILIndexFromHash(hash, numHdrs) ((hash)&((numHdrs) - 1))
#define HEIGHTMASK 0x3
#define HEIGHTSHIFT 2
#define MAXHEIGHT 16
static unsigned
XR_ILHeightFromNum(num)
unsigned num;
{
int i = 0;
for(;;) {
if( ((++i) == MAXHEIGHT) || ((num & HEIGHTMASK) != 0) ) return i;
num >>= HEIGHTSHIFT;
}
}
#define CASE_MASK 0137 /* collapses upper & lower case, other effects too! */
unsigned
XR_ILHashFromSym(sym)
char *sym;
{
unsigned hash = 0;
unsigned c;
if( sym == NIL ) return 0;
for(;;) {
switch(c = *sym++) {
case 0:
case '.':
case '*':
return hash;
}
hash = (hash * 5) + (c & CASE_MASK);
}
}
bool
XR_StrMatchCase(str, pat, caseSensitive)
char *str;
char *pat;
bool caseSensitive;
{
char sc, pc;
for(;;) {
if( (pc = *pat++) == '*' ) return TRUE;
if( (sc = *str++) == 0 ) return ( pc == 0 );
if( sc != pc ) {
if( caseSensitive || (pc == 0) ) return FALSE;
if( isascii(sc) && isupper(sc) ) sc = tolower(sc);
if( isascii(pc) && isupper(pc) ) pc = tolower(pc);
if( sc != pc ) return FALSE;
}
}
}
static bool
XR_ILTypeIsWanted(theType, wantedTypes, ignoredClasses)
unsigned theType;
unsigned wantedTypes;
unsigned ignoredClasses;
{
if( theType & ILSE_EXT ) {
if( ignoredClasses & IGNORE_EXTERNAL ) return FALSE;
} else {
if( ignoredClasses & IGNORE_INTERNAL ) return FALSE;
}
if( wantedTypes == WANT_ALL_TYPES ) return TRUE;
return ((theType & ILSE_TYPE) == (wantedTypes & ILSE_TYPE));
}
static XR_ILSymTabEntry
XR_ILGetMatchingSTEByName(
ilst, ilste, pat, hash, ulCase, wantedTypes, ignoredClasses, numToSkip
)
XR_ILSymTab ilst;
XR_ILSymTabEntry ilste;
char *pat;
unsigned hash;
bool ulCase;
unsigned wantedTypes;
unsigned ignoredClasses;
int numToSkip;
{
if( ilste == NIL ) {
unsigned index = XR_ILIndexFromHash(hash, ilst->ilst_numHdrs);
ilste = ilst->ilst_hdrs[index];
if( numToSkip > 0 ) numToSkip -= 1;
else if( numToSkip < 0 ) numToSkip += 1;
/* else (numToSkip == 0) numToSkip = 0; */
}
for(;;) {
if( ilste == NIL ) break;
if( ilste->ilste_hash == hash ) {
if( XR_ILTypeIsWanted(ilste->ilste_ilse.ilse_type,
wantedTypes, ignoredClasses) ) {
if( XR_StrMatchCase(ilste->ilste_ilse.ilse_name,
pat, ulCase) ) {
if( numToSkip == 0 ) break;
else if( numToSkip > 0 ) numToSkip -= 1;
else /* numToSkip < 0 */ numToSkip += 1;
}
}
}
ilste = ilste->ilste_symNext;
}
return ilste;
}
XR_ILSymEntry
XR_ILGetMatchingSymEntryByName(
ilse, pattern, caseSensitive, wantedTypes, ignoredClasses, numToSkip
)
XR_ILSymEntry ilse;
char *pattern;
bool caseSensitive;
unsigned wantedTypes;
unsigned ignoredClasses;
int numToSkip;
{
unsigned hash;
XR_ILSymTabEntry ilste = ((XR_ILSymTabEntry)(ilse));
if( pattern == NIL ) {
if( ilste == NIL ) return NIL;
pattern = ilste->ilste_ilse.ilse_name;
hash = ilste->ilste_hash;
} else {
hash = XR_ILHashFromSym(pattern);
}
return ((XR_ILSymEntry)
XR_ILGetMatchingSTEByName(
XR_ilSymTab,
ilste,
pattern,
hash,
caseSensitive,
wantedTypes,
ignoredClasses,
numToSkip
)
);
}
/* could be obsolete, but used internally: */
/* static */
XR_ILSymTabEntry
XR_ILLookupSTEByName(ilst, sym, hash, ulCase, extOnly)
XR_ILSymTab ilst;
char *sym;
unsigned hash;
bool ulCase;
bool extOnly;
{
unsigned index;
XR_ILSymTabEntry ilste;
index = XR_ILIndexFromHash(hash, ilst->ilst_numHdrs);
ilste = ilst->ilst_hdrs[index];
for(;;) {
if( ilste == NIL ) break;
if( ilste->ilste_hash == hash ) {
if( (!extOnly) || (ilste->ilste_ilse.ilse_type & ILSE_EXT) ) {
if( XR_StrMatchCase(ilste->ilste_ilse.ilse_name, sym, ulCase))
break;
}
}
ilste = ilste->ilste_symNext;
}
return ilste;
}
static XR_ILSymTabEntry
XR_ILLookupSTEByValue(val)
unsigned val;
{
XR_ILSymTabEntry p, q;
unsigned h1;
p = XR_ilSymTab->ilst_left;
if( (h1 = XR_ilSymTab->ilst_maxHeight) > 0 ) {
h1 -= 1;
for(;;) {
q = p->ilste_valNext[h1];
if( (q == NIL) || (q->ilste_ilse.ilse_value > val) ) {
if( h1 == 0 ) break;
h1 -= 1;
} else {
p = q;
}
}
}
return( p );
}
XR_ILSymEntry
XR_ILGetMatchingSymEntryByValue(
ilse, val, wantedTypes, ignoredClasses, numToSkip
)
XR_ILSymEntry ilse;
unsigned val;
unsigned wantedTypes;
unsigned ignoredClasses;
int numToSkip;
{
XR_ILSymTabEntry p, left;
XR_ILSymTabEntry ilste;
ilste = ( (ilse != NIL)
? ((XR_ILSymTabEntry)(ilse))
: XR_ILLookupSTEByValue(val) );
if( ilste == NIL ) /* can't happen */ {
XR_ConsoleMsg("ILGetMatchingSymEntryByValue botch 0\n");
return NIL;
}
/* What if the type of *ilse is not in wantedTypes? Well, ... */
if( !(XR_ILTypeIsWanted(ilste->ilste_ilse.ilse_type,
wantedTypes, ignoredClasses)) ) {
if( numToSkip <= 0 ) numToSkip -= 1;
}
while( numToSkip < 0 ) {
left = ((ilste->ilste_ilse.ilse_value == 0)
? XR_ilSymTab->ilst_left
: XR_ILLookupSTEByValue(ilste->ilste_ilse.ilse_value-1));
if( left == ilste ) return NIL;
for( p = left; p != ilste; p = p->ilste_valNext[0] ) {
if( XR_ILTypeIsWanted(p->ilste_ilse.ilse_type,
wantedTypes, ignoredClasses) )
numToSkip += 1;
}
ilste = left;
}
for(;;) {
if( ilste == NIL ) return NIL;
if( XR_ILTypeIsWanted(ilste->ilste_ilse.ilse_type,
wantedTypes, ignoredClasses) ) {
if( numToSkip == 0 ) return ((XR_ILSymEntry)(ilste));
numToSkip -= 1;
}
ilste = ilste->ilste_valNext[0];
}
}
static void
XR_ILGrowST(ilst)
XR_ILSymTab ilst;
{
int i, n, newN;
XR_ILSymTabEntry *newHdrs, *pfrom, *pto;
XR_ILSymTabEntry t, revList;
n = ilst->ilst_numHdrs;
newN = n + n;
newHdrs = (XR_ILSymTabEntry *) XR_calloc(
2 * n * sizeof(XR_ILSymTabEntry), 1 );
if( newHdrs == NIL ) return; /* doesn't hurt to fail here ... */
for( i = 0; i < n; i++ ) {
pfrom = ilst->ilst_hdrs + i;
revList = NIL;
while( *pfrom != NIL ) {
t = *pfrom;
*pfrom = t->ilste_symNext;
t->ilste_symNext = revList;
revList = t;
}
while( revList != NIL ) {
t = revList;
revList = t->ilste_symNext;
pto = newHdrs + XR_ILIndexFromHash(t->ilste_hash, newN);
t->ilste_symNext = *pto;
*pto = t;
}
}
ilst->ilst_hdrs = newHdrs;
ilst->ilst_numHdrs = newN;
}
static void
XR_ILInsertSTE(ilst, ilste)
XR_ILSymTab ilst;
XR_ILSymTabEntry ilste;
{
unsigned index, h1;
XR_ILSymTabEntry p, q;
if( ilst->ilst_numEntries >= ilst->ilst_numHdrs ) XR_ILGrowST(ilst);
index = XR_ILIndexFromHash(ilste->ilste_hash, ilst->ilst_numHdrs);
ilste->ilste_symNext = ilst->ilst_hdrs[index];
ilst->ilst_hdrs[index] = ilste;
/* insert entry in new sym list */
ilste->ilste_valNext[0] = NIL;
if( ilst->ilst_newSymsTl == NIL ) {
ilst->ilst_newSymsHd = ilste;
} else {
ilst->ilst_newSymsTl->ilste_valNext[0] = ilste;
}
ilst->ilst_newSymsTl = ilste;
ilst->ilst_numEntries += 1;
}
static void
XR_ILInsertSTEByValue(ilst, ilste)
XR_ILSymTab ilst;
XR_ILSymTabEntry ilste;
{
unsigned index, h1;
XR_ILSymTabEntry p, q;
unsigned newHeight;
newHeight = ilst->ilst_maxHeight;
ilst->ilst_maxHeight = 1;
if( newHeight < ilste->ilste_height ) newHeight = ilste->ilste_height;
h1 = newHeight - 1;
p = ilst->ilst_left;
for(;;) {
q = p->ilste_valNext[h1];
if( (q == NIL)
|| (q->ilste_ilse.ilse_value > ilste->ilste_ilse.ilse_value) ) {
if( h1 < ilste->ilste_height ) {
ilste->ilste_valNext[h1] = q;
p->ilste_valNext[h1] = ilste;
if( h1 == 0 ) break;
}
h1 -= 1;
} else {
p = q;
}
}
ilst->ilst_maxHeight = newHeight;
}
static XR_ILSymTabEntry
XR_ILMakeSTE(ilst, sym, hash, symType, symValue, symSize)
XR_ILSymTab ilst;
char *sym;
unsigned hash;
unsigned symType;
unsigned symValue;
unsigned symSize;
{
unsigned height;
XR_ILSymTabEntry ilste;
static unsigned seqnum = 1;
/* there COULD be interference between processors, but this is okay */
height = XR_ILHeightFromNum(seqnum++);
ilste = (XR_ILSymTabEntry) XR_PZcalloc(
ilst->ilst_zonePtrFree, XR_ILSymTabEntryBytes(height), 1 );
if( ilste == NIL ) {
XR_ILSetError(ilst, TRUE, ENOMEM, "ILMakeSTE: no memory");
return NIL;
}
ilste->ilste_ilse.ilse_name = sym;
ilste->ilste_ilse.ilse_type = symType;
ilste->ilste_ilse.ilse_value = symValue;
ilste->ilste_ilse.ilse_size = symSize;
ilste->ilste_ilse.ilse_ilfe = (XR_ILFileEntry)(ilst->ilst_ilfte);
ilste->ilste_hash = hash;
ilste->ilste_height = height;
return ilste;
}
static void
XR_ILDeleteSTE(ilst, ilste)
XR_ILSymTab ilst;
XR_ILSymTabEntry ilste;
{
unsigned index;
int h1;
XR_ILSymTabEntry p, q;
unsigned newMaxHeight;
/* delete from hash table */
index = XR_ILIndexFromHash(ilste->ilste_hash, ilst->ilst_numHdrs);
p = ilst->ilst_hdrs[index];
if( p == ilste ) {
ilst->ilst_hdrs[index] = ilste->ilste_symNext;
} else {
while( p->ilste_symNext != ilste ) p = p->ilste_symNext;
p->ilste_symNext = p->ilste_symNext->ilste_symNext;
}
ilst->ilst_numEntries -= 1;
/* delete from skip list if present */
/* n.b. code must work with multiple instances of same key! */
if( (newMaxHeight = ilst->ilst_maxHeight) == 0 )
goto NotInSkipList;
ilst->ilst_maxHeight = 1;
h1 = newMaxHeight - 1;
p = ilst->ilst_left;
for(;;) {
q = p->ilste_valNext[h1];
if( (q == NIL) || (q->ilste_ilse.ilse_value
>= ilste->ilste_ilse.ilse_value) ) {
if( h1 < ilste->ilste_height ) break;
h1 -= 1;
} else {
p = q;
}
}
/* ilste is to right of p in skip list, if present at all */
/* h1 == ilste->ilste_height - 1, if ilste present at all */
for(;;) {
q = p->ilste_valNext[h1];
if( q == ilste ) {
break;
} else if( (q == NIL) || (q->ilste_ilse.ilse_value
> ilste->ilste_ilse.ilse_value) ) {
goto NotInSkipList;
} else {
p = q;
}
}
while( h1 >= 0 ) {
p->ilste_valNext[h1] = q->ilste_valNext[h1];
h1 -= 1;
}
while( (newMaxHeight > 1)
&& (ilst->ilst_left->ilste_valNext[newMaxHeight-1] == NIL) ) {
newMaxHeight -= 1;
}
NotInSkipList: ;
ilst->ilst_maxHeight = newMaxHeight;
}
/*
*
* Registration stuff
*
* Exported to IncrementalLoadPrivate.h
*
*/
int
XR_RegisterIncrementalLoadProc(proc, data, nMagics, magics)
XR_ILReaderProc proc;
XR_Pointer data;
int nMagics;
unsigned *magics;
{
XR_ILRegistration ilr;
int i;
ilr = (XR_ILRegistration) XR_malloc(XR_ILRegistrationBytes(nMagics));
if( ilr == NIL ) {
XR_SetErrno(ENOMEM);
return (-ENOMEM);
}
ilr->ilr_proc = proc;
ilr->ilr_data = data;
ilr->ilr_nMagics = nMagics;
for( i = 0; i < nMagics; i++ )
ilr->ilr_magics[i] = magics[i];
(void)XR_MonitorEntry( &(XR_ilSymTab->ilst_ml) );
ilr->ilr_next = XR_ilSymTab->ilst_registrations;
XR_ilSymTab->ilst_registrations = ilr;
(void)XR_MonitorExit( &(XR_ilSymTab->ilst_ml) );
return 0;
}
static bool
XR_ILMagicMatchesRegistration(ilr, m)
XR_ILRegistration ilr;
unsigned m;
{
unsigned *p, *pLim;
if( m == 0 ) return TRUE;
for( ((p = ilr->ilr_magics),(pLim = p + ilr->ilr_nMagics)); p < pLim; p++ )
if( *p == m ) return TRUE;
return FALSE;
}
/*
*
* Utilities for use by registered incremental loading procs
*
* Exported to IncrementalLoadPrivate.h
*
*/
static struct XR_ILErrorRep XR_ilNoMemErrorRep = {
/* ile_fatal */ TRUE,
/* ile_code */ ENOMEM,
/* ile_msg */ "out of memory"
};
XR_ILError
XR_ILMakeError(fatal, code, msg)
bool fatal;
int code;
char * msg;
{
XR_ILError ile;
ile = (XR_ILError) XR_malloc( sizeof(struct XR_ILErrorRep) );
if( ile == NIL ) return( &(XR_ilNoMemErrorRep) );
ile->ile_fatal = fatal;
ile->ile_code = code;
if( msg == NIL ) {
ile->ile_msg = "(no msg)";
} else {
ile->ile_msg = (char *) XR_malloc( strlen(msg)+1 );
if( ile->ile_msg == NIL ) {
ile->ile_msg = "(no memory for msg)";
} else {
strcpy(ile->ile_msg, msg);
}
}
return ile;
}
XR_ILError
XR_ILMakeNoMemError()
{
/* put it in the heap if we can ... */
return XR_ILMakeError(TRUE, ENOMEM, "out of memory");
}
void
XR_ILGetOpenFile(ilst)
XR_ILSymTab ilst;
{
if( ilst->ilst_fd != XR_nullFildes ) return;
ilst->ilst_fd = XR_Open(
ilst->ilst_ilfte->ilfte_ilfe.ilfe_fName, O_RDONLY, 0 );
if( ilst->ilst_fd == XR_nullFildes ) {
XR_ILSetError(ilst, FALSE, XR_GetErrno(),
"ILGetOpenFile: open error");
} else {
struct stat b;
int ans = XR_FStat(ilst->ilst_fd, &b);
if( ans < 0 ) {
XR_ILSetError(ilst, FALSE, XR_GetErrno(),
"ILGetOpenFile: stat error");
} else {
ilst->ilst_ilfte->ilfte_ilfe.ilfe_fSize = b.st_size;
ilst->ilst_ilfte->ilfte_ilfe.ilfe_fMTime = b.st_mtime;
(void)XR_SetGetBlocking(ilst->ilst_fd, XR_UIO_BLOCKING_ALL_DATA);
}
}
}
void
XR_ILCloseFile(ilst)
XR_ILSymTab ilst;
{
if( ilst->ilst_fd != XR_nullFildes ) {
(void) XR_Close(ilst->ilst_fd);
ilst->ilst_fd = XR_nullFildes;
}
}
#if (!PREEMPTABLE_READ)
void
XR_ILRead(ilst, offset, buf, bytes, abortOnError)
XR_ILSymTab ilst;
unsigned offset;
char *buf;
unsigned bytes;
bool abortOnError;
{
int ans;
ans = XR_LSeek(ilst->ilst_fd,
offset+ilst->ilst_ilfte->ilfte_ilfe.ilfe_fOffset, L_SET);
if( ans < 0 ) goto Bad;
ans = XR_Read(ilst->ilst_fd, buf, bytes);
if( ans != bytes ) goto Bad;
return;
Bad:
XR_ILSetError(ilst, abortOnError, XR_GetErrno(), "ILRead: I/O error");
}
#else
#define READALIGN 1024
#define MAXREAD (16*1024)
void
XR_ILRead(ilst, offset, buf, bytes, abortOnError)
XR_ILSymTab ilst;
unsigned offset;
char *buf;
unsigned bytes;
bool abortOnError;
{
int ans, readreq;
if( offset != ((unsigned)(-1)) ) {
ans = XR_LSeek(ilst->ilst_fd,
offset+ilst->ilst_ilfte->ilfte_ilfe.ilfe_fOffset, L_SET);
if( ans < 0 ) goto Bad;
}
if( bytes == 0 ) return;
for(;;) {
if( (readreq = bytes) > MAXREAD )
readreq = MAXREAD - ( ((int)(buf)) & (READALIGN-1) );
ans = XR_Read(ilst->ilst_fd, buf, readreq);
if( ans < 0 ) goto Bad;
buf += ans;
if( (bytes -= ans) == 0 ) return;
if( ans == 0 ) goto Bad;
}
Bad:
XR_ILSetError(ilst, abortOnError, XR_GetErrno(), "ILRead: I/O error");
}
#endif
void
XR_ILAllocSegments(ilst, tBytes, dBytes, bBytes)
XR_ILSymTab ilst;
unsigned tBytes;
unsigned dBytes;
unsigned bBytes;
{
XR_ILFileEntry ilfe = &(ilst->ilst_ilfte->ilfte_ilfe);
unsigned pBytes = 0;
# define ROUNDUPDOUBLE(x) ((((unsigned)(x)) + 0x7) & (~0x7))
ilfe->ilfe_tBytes = tBytes;
ilfe->ilfe_dBytes = dBytes;
ilfe->ilfe_bBytes = bBytes;
ilfe->ilfe_pBytes = pBytes;
if( ilst->ilst_initializationState == ilis_internalizing ) {
ilfe->ilfe_tAddr = ((caddr_t)(0));
ilfe->ilfe_dAddr = ((caddr_t)(tBytes));
ilfe->ilfe_bAddr = ((caddr_t)(tBytes + dBytes));
ilfe->ilfe_pAddr = ((caddr_t)(NIL));
return;
}
ilfe->ilfe_pBytes = ROUNDUPDOUBLE(256 + DEFAULT_PBYTES_FROM_TBYTES(tBytes));
if( ilst->ilst_activePatchSizeProc != NIL ) {
(*(ilst->ilst_activePatchSizeProc))(
ilfe, ilst->ilst_activePatchSizeClientData );
}
ilfe->ilfe_pBytes = ROUNDUPDOUBLE(ilfe->ilfe_pBytes);
pBytes = ilfe->ilfe_pBytes;
if( (pBytes + tBytes) > 0 ) {
ilfe->ilfe_pAddr = XR_PZmalloc( ilst->ilst_zonePtrFree,
pBytes + tBytes );
XR_ILCheckAlloc2(ilst, ilfe->ilfe_pAddr);
ilfe->ilfe_tAddr = (caddr_t)
( ((unsigned)(ilfe->ilfe_pAddr)) + pBytes );
if( pBytes > 0 ) (void) bzero( ilfe->ilfe_pAddr, pBytes );
}
if( dBytes > 0 ) {
ilfe->ilfe_dAddr = XR_PZmalloc( ilst->ilst_zonePtrFree, dBytes );
XR_ILCheckAlloc2(ilst, ilfe->ilfe_dAddr);
}
if( bBytes > 0 ) {
ilfe->ilfe_bAddr = XR_PZcalloc( ilst->ilst_zonePtrFree, bBytes, 1 );
XR_ILCheckAlloc2(ilst, ilfe->ilfe_bAddr);
}
}
static void
XR_ILDoDeferredRelocation(ilst, ilste)
XR_ILSymTab ilst;
XR_ILSymTabEntry ilste;
{
XR_ILRelocItem ilri;
ilri = ilste->ilste_ilri;
ilste->ilste_ilri = NIL;
if( ilst->ilst_initializationState >= ilis_internalized ) {
while( ilri != NIL ) {
# ifdef UNIXDEBUG
printf("ILDRelocate %s ", ilste->ilste_ilse.ilse_name);
printf("addr 0x%x type 0x%x addend 0x%x val 0x%x\n",
ilri->ilri_addr, ilri->ilri_type, ilri->ilri_addend,
ilste->ilste_ilse.ilse_value);
# endif
(*ilri->ilri_proc) (
ilri->ilri_addr,
ilri->ilri_type,
ilri->ilri_addend,
ilste->ilste_ilse.ilse_value
);
ilri = ilri->ilri_next;
}
}
}
static void
XR_ILMoveDeferredRelocationItems(ilst, ilsteOld, ilsteNew)
XR_ILSymTab ilst;
XR_ILSymTabEntry ilsteOld;
XR_ILSymTabEntry ilsteNew;
{
XR_ILRelocItem ilri = NIL;
if( ilst->ilst_initializationState < ilis_internalized ) return;
if( ilsteOld != NIL ) {
ilri = ilsteOld->ilste_ilri;
ilsteOld->ilste_ilri = NIL;
}
if( ilsteNew != NIL ) {
ilsteNew->ilste_ilri = ilri;
}
}
XR_ILSymTabEntry
XR_ILSetSymDefined(ilst, sym, hash, symType, symValue, symSize)
XR_ILSymTab ilst;
char *sym;
unsigned hash;
unsigned symType;
unsigned symValue;
{
XR_ILSymTabEntry steOld;
XR_ILSymTabEntry steNew;
XR_ILContinueAction clientAction;
# ifdef UNIXDEBUG
if( ilst->ilst_initializationState >= ilis_internalized )
printf("ILSetSymDefined(%s, 0x%x, 0x%x)\n", sym, symType, symValue);
# endif
steNew = XR_ILMakeSTE(ilst, sym, hash, symType, symValue, symSize);
if( steNew == NIL ) return NIL;
if( (symType & ILSE_EXT) == 0 ) {
XR_ILInsertSTE(ilst, steNew);
return steNew;
}
steOld = XR_ILLookupSTEByName(ilst, sym, hash,
/*caseSensitive=*/ TRUE, /*externalOnly=*/ TRUE);
clientAction = ilca_continue;
if( ilst->ilst_activeDefProc != NIL ) {
clientAction = (*(ilst->ilst_activeDefProc))(
((XR_ILSymEntry)(steNew)),
((XR_ILSymEntry)(steOld)),
ilst->ilst_activeDefClientData
);
}
if( clientAction == ilca_continue ) {
clientAction = ( ((steOld != NIL) &&
(steOld->ilste_ilse.ilse_type == (ILSE_UNDF|ILSE_EXT)))
? ilca_doBind : ilca_dontBind );
}
switch( clientAction ) {
case ilca_doBind:
if( (steOld != NIL) &&
(steOld->ilste_ilse.ilse_type == (ILSE_UNDF|ILSE_EXT)) ) {
if( steOld->ilste_ilse.ilse_size == 0 )
/* old symbol wasn't common */
ilst->ilst_numUndefined -= 1;
steOld->ilste_ilse.ilse_type = symType;
steOld->ilste_ilse.ilse_value = symValue;
steOld->ilste_ilse.ilse_size = symSize;
steOld->ilste_ilse.ilse_ilfe =
(XR_ILFileEntry) (ilst->ilst_ilfte);
return steOld;
}
XR_ILSetError(ilst, TRUE, XR_EABORTED,
"XR_ILSetSymDefined ilca_doBind error");
return NIL;
case ilca_dontBind:
XR_ILMoveDeferredRelocationItems(ilst, steOld, steNew);
XR_ILInsertSTE(ilst, steNew);
return steNew;
default:
XR_ILSetError(ilst, TRUE, XR_EABORTED, clientAction);
return NIL;
}
}
XR_ILSymTabEntry
XR_ILSetSymCommon(ilst, sym, hash, size)
XR_ILSymTab ilst;
char *sym;
unsigned hash;
unsigned size;
{
XR_ILSymTabEntry steOld, steNew;
XR_ILContinueAction clientAction;
# ifdef UNIXDEBUG
if( ilst->ilst_initializationState >= ilis_internalized )
printf("ILSetSymCommon(%s, %d)\n", sym, size);
# endif
steOld = XR_ILLookupSTEByName(ilst, sym, hash,
/*caseSensitive=*/ TRUE, /*externOnly*/ TRUE);
clientAction = ilca_continue;
if( ilst->ilst_activeCommonProc != NIL ) {
clientAction = (*(ilst->ilst_activeCommonProc))(
sym,
size,
((XR_ILSymEntry)(steOld)),
ilst->ilst_activeCommonClientData
);
}
if( clientAction == ilca_continue ) {
clientAction = ((steOld == NIL) ? ilca_dontBind : ilca_doBind);
}
switch( clientAction ) {
case ilca_dontBind:
steNew = XR_ILMakeSTE( ilst, sym, hash,
(ILSE_UNDF|ILSE_EXT), 0, size );
if( steNew != NIL ) {
XR_ILMoveDeferredRelocationItems(ilst, steOld, steNew);
XR_ILInsertSTE(ilst, steNew);
}
return steNew;
case ilca_doBind:
if( steOld != NIL ) {
if( steOld->ilste_ilse.ilse_type == (ILSE_UNDF|ILSE_EXT) ) {
if( steOld->ilste_ilse.ilse_size == 0 )
ilst->ilst_numUndefined -= 1;
if( steOld->ilste_ilse.ilse_size < size )
steOld->ilste_ilse.ilse_size = size;
}
return steOld;
}
XR_ILSetError(ilst, TRUE, XR_EABORTED,
"XR_ILSetSymCommon ilca_doBind error");
return NIL;
default:
XR_ILSetError(ilst, TRUE, XR_EABORTED, clientAction);
return NIL;
}
}
XR_ILSymTabEntry
XR_ILSetSymReferenced(ilst, sym, hash)
XR_ILSymTab ilst;
char *sym;
unsigned hash;
{
XR_ILSymTabEntry steOld, steNew;
XR_ILContinueAction clientAction;
# ifdef UNIXDEBUG
if( ilst->ilst_initializationState >= ilis_internalized )
printf("ILSetSymReferenced(%s)\n", sym);
# endif
steOld = XR_ILLookupSTEByName(ilst, sym, hash,
/*caseSensitive=*/ TRUE, /*externOnly*/ TRUE);
clientAction = ilca_continue;
if( ilst->ilst_activeRefProc != NIL ) {
clientAction = (*(ilst->ilst_activeRefProc))(
sym,
((XR_ILSymEntry)(steOld)),
ilst->ilst_activeRefClientData
);
}
if( clientAction == ilca_continue ) {
clientAction = ((steOld == NIL) ? ilca_dontBind : ilca_doBind);
}
switch( clientAction ) {
case ilca_dontBind:
steNew = XR_ILMakeSTE( ilst, sym, hash,
(ILSE_UNDF|ILSE_EXT), 0, 0 );
if( steNew != NIL ) {
XR_ILMoveDeferredRelocationItems(ilst, steOld, steNew);
XR_ILInsertSTE( ilst, steNew );
ilst->ilst_numUndefined += 1;
}
return steNew;
case ilca_doBind:
if( steOld != NIL ) return steOld;
XR_ILSetError(ilst, TRUE, XR_EABORTED,
"XR_ILSetSymReferenced ilca_doBind error");
return NIL;
default:
XR_ILSetError(ilst, TRUE, XR_EABORTED, clientAction);
return NIL;
}
}
void
XR_ILRelocate(ilst, ilste, proc, addr, relocType, addend)
XR_ILSymTab ilst;
XR_ILSymTabEntry ilste;
void (*proc)(/*
char *addr,
unsigned relocType, long addend, unsigned val
*/);
char *addr;
unsigned relocType;
long addend;
{
XR_ILRelocItem ilri;
if( ilst->ilst_initializationState >= ilis_internalized ) {
# ifdef UNIXDEBUG
printf("ILRelocate sym %s addr 0x%x type 0x%x addend 0x%x ... ",
ilste->ilste_ilse.ilse_name, addr, relocType, addend );
# endif
if( (ilste->ilste_ilse.ilse_type & ILSE_TYPE) != ILSE_UNDF ) {
# ifdef UNIXDEBUG
printf("immediate 0x%x\n", ilste->ilste_ilse.ilse_value);
# endif
(*proc)(addr, relocType, addend, ilste->ilste_ilse.ilse_value);
} else {
XR_ILRelocItem ilri;
# ifdef UNIXDEBUG
printf("deferred\n");
# endif
ilri = (XR_ILRelocItem) XR_PZmalloc(
ilst->ilst_zonePerCommit, sizeof(struct XR_ILRelocItemRep) );
XR_ILCheckAlloc2(ilst, ilri)
ilri->ilri_proc = proc;
ilri->ilri_addr = addr;
ilri->ilri_type = relocType;
ilri->ilri_addend = addend;
ilri->ilri_next = ilste->ilste_ilri;
ilste->ilste_ilri = ilri;
}
}
}
static void XR_ILRecordCommon();
static void XR_ILRecordNewFiles();
/*
* Insert new symbols preparatory to commit.
* IMPORTANT: this either succeeds or has no effect.
*/
static XR_ILError
XR_ILInsertNewSymbols(ilst)
XR_ILSymTab ilst;
{
XR_ILSymTabEntry ilste;
unsigned disp, len, cBytes;
caddr_t cAddr;
# ifdef UNIXDEBUG
printf("ILInsertNewSymbols\n");
# endif
/* if we're just internalizing symbols, skip common */
/* processing and relocation */
if( ilst->ilst_initializationState == ilis_internalizing ) {
ilst->ilst_undefinedSymsHdCache = NIL;
while( (ilste = ilst->ilst_newSymsHd) != NIL ) {
ilst->ilst_newSymsHd = ilste->ilste_valNext[0];
ilste->ilste_valNext[0] = NIL;
if( (ilste->ilste_ilse.ilse_type & ILSE_TYPE) != ILSE_ABS ) {
XR_ILInsertSTEByValue(ilst, ilste);
}
}
ilst->ilst_newSymsTl = NIL;
return;
}
/* compute offsets in common seg for all common defs */
/* compute size of common seg */
disp = 0;
for(
ilste = ilst->ilst_newSymsHd;
ilste != NIL;
ilste = ilste->ilste_valNext[0]
) {
if( ilste->ilste_ilse.ilse_type != (ILSE_UNDF|ILSE_EXT) )
continue;
len = ilste->ilste_ilse.ilse_size;
XR_ILAssert( (len > 0), "ILAllocateCommon a0" );
if( len & 0x1 ) {
/* nothing */
} else if( len & 0x3 ) {
disp = (disp + 0x1) & (~0x1);
} else if( len & 0x7 ) {
disp = (disp + 0x3) & (~0x3);
} else {
disp = (disp + 0x7) & (~0x7);
}
ilste->ilste_ilse.ilse_value = disp;
disp += len;
}
cBytes = (disp + 0x7) & (~0x7);
/* allocate common segment */
cAddr = NIL;
if( cBytes > 0 ) {
cAddr = (caddr_t) XR_PZcalloc(ilst->ilst_zonePtrFree, cBytes, 1);
XR_ILCheckAlloc(cAddr);
}
ilst->ilst_ilfte->ilfte_ilfe.ilfe_cBytes = cBytes;
ilst->ilst_ilfte->ilfte_ilfe.ilfe_cAddr = cAddr;
/* define common syms and do deferred relocation, insert syms by value */
ilst->ilst_undefinedSymsHdCache = NIL;
while( (ilste = ilst->ilst_newSymsHd) != NIL ) {
ilst->ilst_newSymsHd = ilste->ilste_valNext[0];
ilste->ilste_valNext[0] = NIL;
if( ilste->ilste_ilse.ilse_type == (ILSE_UNDF|ILSE_EXT) ) {
ilste->ilste_ilse.ilse_type = (ILSE_BSS|ILSE_EXT);
ilste->ilste_ilse.ilse_value =
(unsigned) (cAddr + ilste->ilste_ilse.ilse_value);
XR_ILRecordCommon(ilst, ilste);
}
XR_ILDoDeferredRelocation(ilst, ilste); /* can't fail! */
if( (ilste->ilste_ilse.ilse_type & ILSE_TYPE) != ILSE_ABS ) {
XR_ILInsertSTEByValue(ilst, ilste);
}
}
ilst->ilst_newSymsTl = NIL;
}
static void
XR_ILDiscardNewSymbols(ilst)
XR_ILSymTab ilst;
{
XR_ILSymTabEntry ilste, *hp, *hpLim;
unsigned sinceSeqNum;
sinceSeqNum = ilst->ilst_ilfte->ilfte_ilfe.ilfe_seqNum;
# ifdef UNIXDEBUG
printf("ILDiscardNewSymbols(since: %d)\n", sinceSeqNum);
# endif
ilst->ilst_undefinedSymsHdCache = NIL;
ilst->ilst_newSymsHd = NIL;
ilst->ilst_newSymsTl = NIL;
hp = ilst->ilst_hdrs;
hpLim = hp + ilst->ilst_numHdrs;
while( hp < hpLim ) {
if( ((ilste = *hp) != NIL)
&& (ilste->ilste_ilse.ilse_ilfe->ilfe_seqNum > sinceSeqNum) ) {
XR_ILDeleteSTE(ilst, ilste);
} else {
hp++;
}
}
ilst->ilst_numUndefined = 0;
}
/*
*
* Exported to IncrementalLoad.h
*
*/
bool
XR_ILSymIsInRecentLoad(ilse)
XR_ILSymEntry ilse;
{
XR_ILFileTabEntry ilfte;
unsigned seqNum;
if( (ilse == NIL) || ((seqNum = ilse->ilse_ilfe->ilfe_seqNum) == 0) )
return FALSE; /* client error, really */
ilfte = XR_ilSymTab->ilst_ilfte;
for(;;) {
if( seqNum >= ilfte->ilfte_ilfe.ilfe_seqNum )
/* changed from > to >= April 6, 1990 ajd */
return( TRUE );
ilfte = ilfte->ilfte_prev;
if( ilfte->ilfte_ilfe.ilfe_commitPoint )
return( FALSE );
}
}
XR_Pointer
XR_ILLookupProc(name, externOnly, recentOnly)
char *name;
bool externOnly;
bool recentOnly;
{
XR_ILSymEntry ilse;
XR_Pointer procToCall = NIL;
ilse = XR_ILGetMatchingSymEntryByName(
/*ilse*/ NIL,
/*pattern*/ name,
/*caseSensitive*/ TRUE,
/*wantedTypes*/ ILSE_TEXT,
/*ignoredClasses*/ (externOnly ? IGNORE_INTERNAL : IGNORE_NONE),
/*numToSkip*/ 0
);
if( ilse != NIL ) {
if( (!recentOnly) || XR_ILSymIsInRecentLoad(ilse) ) {
procToCall = ((XR_Pointer)(ilse->ilse_value));
}
}
return procToCall;
}
void
XR_ILEnumerateUndefinedSyms(func, clientData)
bool (*func)(/*XR_SymEntry se, void *clientData*/);
char *clientData;
{
XR_ILSymTab ilst;
XR_ILSymTabEntry ilste;
ilst = XR_ilSymTab;
if( ilst->ilst_numUndefined == 0 ) return;
if( func == NIL ) return;
if( (ilste = ilst->ilst_undefinedSymsHdCache) == NIL )
ilste = ilst->ilst_newSymsHd;
while( ilste != NIL ) {
if( ((ilste->ilste_ilse.ilse_type & ILSE_TYPE) == ILSE_UNDF)
&& (ilste->ilste_ilse.ilse_size == 0) ) {
if( ilst->ilst_undefinedSymsHdCache == NIL )
ilst->ilst_undefinedSymsHdCache = ilste;
if( !( (*func)(&(ilste->ilste_ilse), clientData) ) ) return;
}
ilste = ilste->ilste_valNext[0];
}
}
static XR_ILError
XR_ILCallReaderProc(ilst, ilfte, op)
XR_ILSymTab ilst;
XR_ILFileTabEntry ilfte;
XR_ILOp op;
{
XR_ILReaderProc proc;
XR_ILError theResult;
XR_ILRegistration ilr;
if( ilfte == NIL ) XR_Panic("ILCallReaderProc 0");
if( (ilr = ilfte->ilfte_ilr) == NIL ) return NIL;
if( (proc = ilr->ilr_proc) == NIL ) return NIL;
ilst->ilst_opArg = op;
ilst->ilst_ilfteArg = ilfte;
ilst->ilst_result = NIL;
ilst->ilst_readerProcData = ilr->ilr_data;
(void) bzero(ilst->ilst_fileData, (sizeof ilst->ilst_fileData));
/* not necessary, but ... */
(*proc)(ilst);
theResult = ilst->ilst_result;
ilst->ilst_result = NIL;
ilst->ilst_opArg = ilOpNone;
ilst->ilst_ilfteArg = NIL;
ilst->ilst_readerProcData = NIL;
(void) bzero(ilst->ilst_fileData, (sizeof ilst->ilst_fileData));
return theResult;
}
static void
XR_ILCommitFiles(ilst, ilfte)
XR_ILSymTab ilst;
XR_ILFileTabEntry ilfte;
{
XR_ILError ile;
if( ilfte == NIL ) XR_Panic("ILCommitFiles 0");
if( ilfte->ilfte_ilfe.ilfe_commitPoint ) return;
XR_ILCommitFiles(ilst, ilfte->ilfte_prev);
ile = XR_ILCallReaderProc(ilst, ilfte, ilOpCommit);
if( ile != NIL ) /* this is a reader proc bug */ {
XR_ConsoleMsg("ILCommitFile %s error %s\n",
ilfte->ilfte_ilfe.ilfe_fName, ile->ile_msg);
XR_Panic("ILCommitFiles 1");
}
if( ilfte->ilfte_gcRootEnumerator == NIL ) {
XR_ILSetGCRootEnumerator(
ilst,
ilfte,
( (ilst->ilst_initializationState >= ilis_internalized)
? XR_ILDefaultGCRootEnumerator
: XR_ILDefaultBootFileGCRootEnumerator ),
((XR_Pointer)(ilfte))
);
}
/* ??? INTERIM: if not internalizing, notify collector of new roots ??? */
if( ilst->ilst_initializationState >= ilis_internalized )
XR_ILTellCollectorAboutRoots(ilst, ilfte);
}
XR_ILError
XR_CommitIncrementalLoad()
{
XR_ILSymTab ilst = XR_ilSymTab;
XR_ILFileTabEntry ilfte = XR_ilSymTab->ilst_ilfte;
XR_ILError result;
if( ilst->ilst_numUndefined != 0 ) {
return XR_ILMakeError(FALSE, EINVAL,
"CommitIncrementalLoad: undefined symbols exist");
}
result = XR_ILInsertNewSymbols(ilst);
ilfte->ilfte_revertCookie = XR_PZremember(ilst->ilst_zone);
ilfte->ilfte_revertCookiePtrFree = XR_PZremember(ilst->ilst_zonePtrFree);
XR_ILCommitFiles(ilst, ilfte);
XR_ILRecordNewFiles(ilst);
ilfte->ilfte_ilfe.ilfe_commitPoint = TRUE;
XR_PZrevert(ilst->ilst_zonePerCommit, XR_PZ_FREE_ALL);
XR_PZrevert(ilst->ilst_zonePerFile, XR_PZ_FREE_ALL);
return NIL;
}
static void
XR_ILDiscardActiveLoads(ilst, target)
XR_ILSymTab ilst;
XR_ILFileTabEntry target;
{
XR_ILFileTabEntry ilfte;
bool sawTarget;
XR_ILRegistration ilr;
XR_ILReaderProc proc;
sawTarget = (target == NIL);
XR_LogVMsg "DiscardActiveLoads target 0x%x\n", target);
ilfte = ilst->ilst_ilfte;
for(;;) {
if( ilfte == NIL ) break;
if( (ilfte->ilfte_ilfe.ilfe_commitPoint) && sawTarget ) break;
(void)XR_ILCallReaderProc(ilst, ilfte, ilOpAbort);
if( ilfte == target ) sawTarget = TRUE;
ilfte = ilfte->ilfte_prev;
}
ilst->ilst_ilfte = ilfte;
XR_LogVMsg "DiscardActiveLoads about to discard symbols ...\n");
XR_ILDiscardNewSymbols(ilst);
XR_LogVMsg "DiscardActiveLoads about to free memory ...\n");
XR_PZrevert(ilst->ilst_zone, ilfte->ilfte_revertCookie);
XR_PZrevert(ilst->ilst_zonePtrFree, ilfte->ilfte_revertCookiePtrFree);
XR_PZrevert(ilst->ilst_zonePerFile, XR_PZ_FREE_ALL);
XR_PZrevert(ilst->ilst_zonePerCommit, XR_PZ_FREE_ALL);
XR_LogVMsg "DiscardActiveLoads done\n");
}
XR_ILError
XR_AbortIncrementalLoad(ilfe)
XR_ILFileEntry ilfe;
{
XR_ILSymTab ilst = XR_ilSymTab;
XR_ILDiscardActiveLoads( ilst, ((XR_ILFileTabEntry)(ilfe)) );
return NIL;
}
XR_ILError
XR_ILLoadFile(fName, fOffset, fMagic,
refProc, refClientData, defProc, defClientData,
commonProc, commonClientData, patchSizeProc, patchSizeClientData)
char *fName;
long fOffset;
unsigned fMagic;
XR_ILContinueAction (*refProc)(/*
char *sym,
XR_ILSymEntry ilseOld,
void *clientData
*/);
char *refClientData;
XR_ILContinueAction (*defProc)(/*
XR_ILSymEntry ilseNew,
XR_ILSymEntry ilseOld,
void *clientData
*/);
char *defClientData;
XR_ILContinueAction (*commonProc)(/*_
char *sym,
unsigned size,
XR_ILSymEntry ilseOld,
void *clientData
*/);
char *commonClientData;
void (*patchSizeProc)(/*
XR_ILFileEntry ilfe,
void *clientData
*/);
char *patchSizeClientData;
{
XR_ILSymTab ilst = XR_ilSymTab;
XR_ILRegistration ilr;
XR_ILFileTabEntry ilfte;
XR_ILError theResult = NIL;
if( ilst == NIL ) XR_Panic("XR_ILLoadFile 0");
if( ilst->ilst_initializationState < ilis_internalizing ) {
return XR_ILMakeError( TRUE, EINVAL,
"ILLoadFile: uninitialized" );
}
if( ilst->ilst_fd != (-1) ) XR_Panic("XR_ILLoadFile 1");
ilst->ilst_fd = -1; /* redundant ??? */
/*
* Set up ...
*/
/* create file table entry */
ilfte = XR_ILCreateILFTE(ilst, fName, fOffset);
XR_ILCheckAlloc(ilfte);
ilfte->ilfte_prev = ilst->ilst_ilfte;
ilst->ilst_ilfte = ilfte;
/* store callbacks for reader proc */
ilst->ilst_activeRefProc = refProc;
ilst->ilst_activeRefClientData = refClientData;
ilst->ilst_activeDefProc = defProc;
ilst->ilst_activeDefClientData = defClientData;
ilst->ilst_activeCommonProc = commonProc;
ilst->ilst_activeCommonClientData = commonClientData;
ilst->ilst_activePatchSizeProc = patchSizeProc;
ilst->ilst_activePatchSizeClientData = patchSizeClientData;
/*
* Try each registered reader in turn ...
*/
for(
ilr = XR_ilSymTab->ilst_registrations;
ilr != NIL;
ilr = ilr->ilr_next
) {
if( !XR_ILMagicMatchesRegistration(ilr, fMagic) ) continue;
/* store reader proc id in file table */
ilfte->ilfte_ilfe.ilfe_fMagic = fMagic;
ilfte->ilfte_ilr = ilr;
ilfte->ilfte_readerPrivateState = NIL;
/* call the proc */
theResult = XR_ILCallReaderProc(
ilst,
ilfte,
( (ilst->ilst_initializationState >= ilis_internalized)
? ilOpLoad
: ilOpInternalize)
);
/* if successful, break */
if( theResult == NIL ) goto Done;
/* reader proc failed ... remove reader proc id from file table */
ilfte->ilfte_ilr = NIL;
ilfte->ilfte_readerPrivateState = NIL;
/* analyze failure code to decide whether to continue or abort */
if( theResult->ile_fatal ) goto Done;
switch( theResult->ile_code ) {
/* errors specific to this load proc */
case EDOM:
/* "domain error" -- magic was 0, but I can't parse file */
continue;
case ENOEXEC:
/* "no exec" -- file not specified format, or garbage */
goto Done;
/* errors that all load procs may encounter */
case ENOENT:
case EACCES:
goto Done;
/* unknown errors */
default:
continue;
}
}
/* fell thru -- didn't find applicable loader */
theResult = XR_ILMakeError(FALSE, EINVAL,
"ILLoadFile: unknown file type");
/*
* Done -- success or hard failure ...
*/
Done:
/* close file if open */
XR_ILCloseFile(ilst);
/* clean up reader proc callbacks */
ilst->ilst_activeRefProc = NIL;
ilst->ilst_activeRefClientData = NIL;
ilst->ilst_activeDefProc = NIL;
ilst->ilst_activeDefClientData = NIL;
ilst->ilst_activeCommonProc = NIL;
ilst->ilst_activeCommonClientData = NIL;
ilst->ilst_activePatchSizeProc = NIL;
ilst->ilst_activePatchSizeClientData = NIL;
/* discard data from unsuccessful loads */
if( theResult != NIL ) {
if( theResult->ile_fatal ) {
XR_ILDiscardActiveLoads(ilst, NIL);
} else {
ilst->ilst_ilfte = ilst->ilst_ilfte->ilfte_prev;
}
}
/* free temporary space */
XR_PZrevert(ilst->ilst_zonePerFile, XR_PZ_FREE_ALL);
return theResult;
}
static void XR_ILInitInfoFile();
/*
* Start of the world ...
*/
XR_ILError
XR_InitializeIncrementalLoader(fName)
char *fName;
{
extern void XR_run_IncrementalLoadDEFAULT();
XR_ILError theResult = NIL;
XR_ILSymTab ilst = XR_ilSymTab;
XR_ILFileTabEntry ilfte;
XR_ILSymTabEntry ilste;
if( ilst->ilst_initializationState == ilis_initial ) {
/* finish initialization of *ilst */
XR_InitializeMonitor(&(ilst->ilst_ml));
XR_InitializeCondition(&(ilst->ilst_avail), XR_WAIT_FOREVER);
XR_EnableAborts(&(ilst->ilst_avail));
ilst->ilst_numHdrs = XR_ILST_INIT_NUM_HDRS;
ilst->ilst_hdrs = (XR_ILSymTabEntry *) XR_calloc(
XR_ILST_INIT_NUM_HDRS * sizeof(XR_ILSymTabEntry), 1 );
XR_ILCheckAlloc( ilst->ilst_hdrs );
ilfte = XR_ILCreateILFTE(ilst, NIL, 0);
XR_ILCheckAlloc( ilfte );
ilfte->ilfte_ilfe.ilfe_commitPoint = TRUE;
ilfte->ilfte_revertCookie = XR_PZ_FREE_ALL;
ilfte->ilfte_revertCookiePtrFree = XR_PZ_FREE_ALL;
ilst->ilst_ilfte = ilfte;
ilste = (XR_ILSymTabEntry) XR_calloc(
XR_ILSymTabEntryBytes(MAXHEIGHT), 1 );
XR_ILCheckAlloc( ilste );
ilste->ilste_height = MAXHEIGHT;
ilste->ilste_ilse.ilse_ilfe = ((XR_ILFileEntry)(ilfte));
ilst->ilst_left = ilste;
ilst->ilst_fd = -1;
ilst->ilst_zonePerFile = XR_PZCreate(FALSE, 0);
XR_ILCheckAlloc( ilst->ilst_zonePerFile );
ilst->ilst_zonePerCommit = XR_PZCreate(FALSE, 0);
XR_ILCheckAlloc( ilst->ilst_zonePerCommit );
ilst->ilst_zone = XR_PZCreate(FALSE, 0);
XR_ILCheckAlloc( ilst->ilst_zone );
ilst->ilst_zonePtrFree = XR_PZCreate(TRUE, 0);
XR_ILCheckAlloc( ilst->ilst_zonePtrFree );
XR_ILInitInfoFile(ilst);
ilst->ilst_initializationState = ilis_allocated;
}
XR_run_IncrementalLoadDEFAULT();
theResult = XR_LockIncrementalLoadState(TRUE);
if( theResult != NIL ) return theResult;
if( fName == NIL ) XR_Panic("InitializeIncrementalLoader 0");
ilst->ilst_initializationState = ilis_internalizing;
theResult = XR_ILLoadFile(
/* file name */ fName,
/* offset */ 0,
/* fMagic */ 0,
/* refProc */ NIL,
/* refClientData */
/* defProc */ NIL,
/* defClientData */ NIL,
/* commonProc */ NIL,
/* commonClientData */ NIL,
/* patchSizeProc */ NIL,
/* patchSizeClientData */ NIL
);
if( theResult == NIL ) {
theResult = XR_CommitIncrementalLoad();
ilst->ilst_initializationState = ilis_internalized;
}
if( theResult != NIL ) {
(void) XR_AbortIncrementalLoad();
ilst->ilst_initializationState = ilis_allocated;
theResult->ile_fatal = TRUE;
}
(void) XR_UnlockIncrementalLoadState();
return theResult;
}
/*
* Setup -- called before virtual processors are forked
*/
XR_ILSymTab XR_ilSymTab = NIL;
void
XR_SetupIncrementalLoader()
{
XR_ILSymTab ilst;
/*
* allocate symbol table struct
*
* leave remaining initialization to XR_InitializeIncrementalLoader()
*/
ilst = (XR_ILSymTab)
XR_AllocSharedSysMem( sizeof(struct XR_ILSymTabRep) );
(void) bzero( ilst, sizeof(struct XR_ILSymTabRep) );
XR_ilSymTab = ilst;
}
/*
* dbx initialization file
*/
static void
XR_ILRecordCommon(ilst, ilste)
XR_ILSymTab ilst;
XR_ILSymTabEntry ilste;
{
/* write the entry for the common symbol in the file-and-commons-info */
if (ilst->ilst_infoFile == -1) return;
XR_Msg(ilst->ilst_infoFile, "C: %x %s\n",
ilste->ilste_ilse.ilse_value,
ilste->ilste_ilse.ilse_name );
}
static void
XR_ILRecordNewFiles(ilst)
XR_ILSymTab ilst;
{
/* write the entry for the new files in the file-and-commons-info */
XR_ILFileTabEntry ilfte;
XR_Fildes fd;
if ((fd = ilst->ilst_infoFile) == -1) return;
ilfte = ilst->ilst_ilfte;
while( !(ilfte->ilfte_ilfe.ilfe_commitPoint) ) {
/* write the record for ilfte */
XR_Msg(fd, "F: %x %x %x %x %s\n",
ilfte->ilfte_ilfe.ilfe_tAddr,
ilfte->ilfte_ilfe.ilfe_dAddr,
ilfte->ilfte_ilfe.ilfe_bAddr,
ilfte->ilfte_ilfe.ilfe_fOffset,
ilfte->ilfte_ilfe.ilfe_fName );
ilfte = ilfte->ilfte_prev;
}
}
void
XR_ILGetInfoFileName(buf)
char *buf;
{
char *(XR_get_loader_directory());
int XR_GetPID();
XR_SPrintF(buf, "%s/ILsymtab.pid%d",
XR_get_loader_directory(), XR_GetPID() );
}
static void
XR_ILCleanUpInfoFile(name)
char *name;
{
(void)unlink(name);
}
static void (*XR_ilCleanUpInfoFile) = XR_ILCleanUpInfoFile;
static void
XR_ILInitInfoFile(ilst)
XR_ILSymTab ilst;
{
char *name = (char *) XR_pointerfree_new(256);
XR_ILGetInfoFileName(name);
ilst->ilst_infoFileName = name;
if ((ilst->ilst_infoFile =
XR_Open(name, O_RDWR | O_TRUNC | O_CREAT, 0777)) < 0) {
ilst->ilst_infoFile = -1;
}
(void)XR_RegisterTerminationCleanupProc(
&XR_ilCleanUpInfoFile, name );
} /* XR_ILInitInfoFile */